/*
 * Created on 28. aug.. 2006
 * Created by Tomas Ekeli
 */
package placing;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

import people.Group;
import people.Person;
import people.Reserver;

/**
 * 
 * A Reservation stores who can be assigned to a place. It can store one or
 * more Person(s) and/or Group(s).
 * 
 * @author Tomas Ekeli
 *
 */
public class Reservation implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = -6590203684801000825L;
	private LinkedList<Person> ungroupedPersonsList;
	private LinkedList<Group> groupsList;
	
	
	public String toString() {
		String sReturnMe = "";
		if (!ungroupedPersonsList.isEmpty()) {
			for (Person p : ungroupedPersonsList) {
				sReturnMe += p.getName() + ";";
			}
		}
		if (!groupsList.isEmpty()) {
			for (Group g : groupsList) {
				sReturnMe += g.getName() + ";";
			}
		}
		
		return sReturnMe;
	}
	
	/**
	 * A Reservation stores a set of Groups and Persons, and can check
	 * whether a Person is included in the Reservation.
	 *
	 */
	protected Reservation() {
		ungroupedPersonsList = new LinkedList<Person>();
		groupsList = new LinkedList<Group>();
	}
	
	/**
	 * Sets this Reservation to include the Reserver
	 * 
	 * @param r The reserver of this
	 */
	protected void reserve(Reserver r) {
		if (r.getClass() == Person.class) {
			ungroupedPersonsList.add((Person)r);
		}
		else {
			if (r.getClass() == Group.class) {
				groupsList.add((Group)r);
			}
		}
		
	}
	
	
	/**
	 * Removes the Person from the Reservation. This only removes the Person
	 * if he/she has a Reservation as a lone Person. Any group-memberships and
	 * the eligibility for this Reservation as a result of these will remain
	 * unchanged.
	 * @param p The Person to remove
	 */
	protected void removeReservation(Person p) {
		ungroupedPersonsList.remove(p);
	}
	
	/**
	 * Removes the Group from the Reservation. This remove the Group as a whole.
	 * If members of the Group are valid for this Reservation as lone Persons
	 * they will still validate.
	 * @param g
	 */
	protected void removeReservation(Group g) {
		groupsList.remove(g);
	}
	
	protected boolean validate(Reserver r) {
		if (r.getClass() == Person.class) {
			return validate((Person)r);
		}
		else {
			return validate((Group)r);
		}
	}

	/**
	 * Clears the Reservation. After this method no <code>validate()</code>
	 * will evaluate to <code>true</code> untill new Persons or Groups are
	 * added.
	 *
	 */
	protected void clear() {
		ungroupedPersonsList.clear();
		groupsList.clear();
	}

	/**
	 * Checks whether this Reservation is valid for the Person given.
	 * @param p The Person to check for
	 * @return <code>true</code> iff the Person is included in the Reservation
	 */
	private boolean validate(Person p) {
		//check all lone persons
		for (Person currentPerson : ungroupedPersonsList) {
			if(currentPerson.equals(p)) {
				return true;
			}
		}
		//check all groups
		for (Group currentGroup : groupsList) {
			if (currentGroup.inGroup(p)) {
				return true;
			}
		}
		
		//not reserved for this Person
		return false;
	}
	
	/**
	 * 
	 * @param g The Group to check a reservation for
	 * @return <code>true</code> iff the Reservation is valid for the Group
	 * (even if all persons in the Group are valid, this may return 
	 * <code>false</code> if the Group as a whole are not valid=.
	 */
	private boolean validate(Group g) {
		if (groupsList.contains(g)) {
			return true;
		}
		return false;
	}

	public List<Person> getPersons() {
		return new LinkedList<Person>(ungroupedPersonsList);
	}
	
	public List<Group> getGroups() {
		return new LinkedList<Group>(groupsList);
	}
}
